/**
 * UniApp 请求封装
 * 支持请求拦截、响应拦截、错误处理、loading等功能
 */

// 配置常量
const BASE_URL = 'https://api.jyoungy.com/wxapi' // 请根据实际情况修改
// const BASE_URL = 'http://120.26.12.196:1920' // 请根据实际情况修改
const TIMEOUT = 10000 // 请求超时时间（毫秒）

// 状态码映射
const STATUS_CODE = {
  SUCCESS: 200,
  UNAUTHORIZED: 401,
  FORBIDDEN: 403,
  NOT_FOUND: 404,
  SERVER_ERROR: 500
}

class Request {
  constructor() {
    this.baseURL = BASE_URL
    this.timeout = TIMEOUT
    this.interceptors = {
      request: {
        use: null
      },
      response: {
        use: null
      }
    }
  }

  /**
   * 设置请求拦截器
   * @param {Function} fulfilled 成功回调
   * @param {Function} rejected 失败回调
   */
  setRequestInterceptor(fulfilled, rejected) {
    this.interceptors.request.use = { fulfilled, rejected }
  }

  /**
   * 设置响应拦截器
   * @param {Function} fulfilled 成功回调
   * @param {Function} rejected 失败回调
   */
  setResponseInterceptor(fulfilled, rejected) {
    this.interceptors.response.use = { fulfilled, rejected }
  }

  /**
   * 将对象转换为formData格式
   * @param {Object} obj 要转换的对象
   * @returns {String} formData格式的字符串
   */
  objectToFormData(obj) {
    if (!obj || typeof obj !== 'object') {
      return ''
    }
    
    const formData = []
    
    // 递归处理嵌套对象和数组
    const processValue = (key, value) => {
      if (value === null || value === undefined) {
        return
      }
      
      if (Array.isArray(value)) {
        // 处理数组
        value.forEach((item, index) => {
          processValue(`${key}[${index}]`, item)
        })
      } else if (typeof value === 'object') {
        // 处理嵌套对象
        Object.keys(value).forEach(subKey => {
          processValue(`${key}[${subKey}]`, value[subKey])
        })
      } else {
        // 处理基本类型
        formData.push(encodeURIComponent(key) + '=' + encodeURIComponent(value))
      }
    }
    
    // 遍历对象属性
    for (const key in obj) {
      if (obj.hasOwnProperty(key)) {
        processValue(key, obj[key])
      }
    }
    
    return formData.join('&')
  }

  /**
   * 处理请求配置
   * @param {Object} config 请求配置
   * @returns {Object} 处理后的配置
   */
  processRequestConfig(config) {
    // 设置默认配置
    const defaultConfig = {
      url: '',
      method: 'GET',
      data: {},
      header: {
        'Content-Type': 'application/json;charset=UTF-8'
      },
      timeout: this.timeout,
      dataType: 'json',
      responseType: 'text',
      sslVerify: true,
      withCredentials: false,
      firstIpv4: false
    }

    // 合并配置
    const mergedConfig = { ...defaultConfig, ...config }

    // 处理POST、PUT、DELETE请求，转换为formData格式
    if (['POST', 'PUT', 'DELETE'].includes(mergedConfig.method) && 
        mergedConfig.data && 
        typeof mergedConfig.data === 'object' &&
        !config.header?.['Content-Type'] && 
        !config.header?.['content-type']) {
      mergedConfig.header['Content-Type'] = 'application/x-www-form-urlencoded'
      mergedConfig.data = this.objectToFormData(mergedConfig.data)
    }

    // 处理URL
    if (!mergedConfig.url.startsWith('http')) {
      mergedConfig.url = this.baseURL + mergedConfig.url
    }

    // 添加token（如果存在）
    const token = uni.getStorageSync('token')
    if (token) {
      mergedConfig.header.token = `${token}`
    }

    // 执行请求拦截器
    if (this.interceptors.request.use && this.interceptors.request.use.fulfilled) {
      try {
        return this.interceptors.request.use.fulfilled(mergedConfig)
      } catch (error) {
        if (this.interceptors.request.use.rejected) {
          this.interceptors.request.use.rejected(error)
        }
        throw error
      }
    }

    return mergedConfig
  }

  /**
   * 处理响应数据
   * @param {Object} response 响应对象
   * @returns {Object} 处理后的响应
   */
  processResponse(response) {
    // 执行响应拦截器
    if (this.interceptors.response.use && this.interceptors.response.use.fulfilled) {
      try {
        return this.interceptors.response.use.fulfilled(response)
      } catch (error) {
        if (this.interceptors.response.use.rejected) {
          this.interceptors.response.use.rejected(error)
        }
        throw error
      }
    }

    return response
  }

  /**
   * 错误处理
   * @param {Object} error 错误对象
   * @param {Boolean} showError 是否显示错误提示
   */
  handleError(error, showError = true) {
    let errorMessage = '请求失败'

    if (error.errMsg) {
      // 网络错误
      if (error.errMsg.includes('timeout')) {
        errorMessage = '请求超时，请检查网络连接'
      } else if (error.errMsg.includes('fail')) {
        errorMessage = '网络连接失败，请检查网络设置'
      }
    } else if (error.statusCode) {
      // HTTP状态码错误
      switch (error.statusCode) {
        case STATUS_CODE.UNAUTHORIZED:
          errorMessage = '登录已过期，请重新登录'
          // 可以在这里处理token过期的逻辑
          // uni.removeStorageSync('token')
          // uni.reLaunch({ url: '/pages/login/login' })
          break
        case STATUS_CODE.FORBIDDEN:
          errorMessage = '没有权限访问'
          break
        case STATUS_CODE.NOT_FOUND:
          errorMessage = '请求的资源不存在'
          break
        case STATUS_CODE.SERVER_ERROR:
          errorMessage = '服务器内部错误'
          break
        default:
          errorMessage = `请求失败 (${error.statusCode})`
      }
    }

    if (showError) {
      uni.showToast({
        title: errorMessage,
        icon: 'none',
        duration: 2000
      })
    }

    return Promise.reject({ ...error, message: errorMessage })
  }

  /**
   * 发送请求
   * @param {Object} config 请求配置
   * @returns {Promise} 请求Promise
   */
  request(config) {
    return new Promise((resolve, reject) => {
      try {
        // 处理请求配置
        const processedConfig = this.processRequestConfig(config)

        // 显示loading
        if (config.loading) {
          uni.showLoading({
            title: config.loadingText || '加载中...',
            mask: true
          })
        }
        // 发送请求
        uni.request({
          ...processedConfig,
          success: (response) => {
            try {
              // 隐藏loading
              if (config.loading) {
                uni.hideLoading()
              }

              // 处理响应
              const processedResponse = this.processResponse(response)
              
              // 检查业务状态码
              if (processedResponse.statusCode === STATUS_CODE.SUCCESS) {
                const { data } = processedResponse
                
                // 这里可以根据后端接口规范调整
                if (data.code === 0 || data.success === true) {
                  resolve(data.data || data)
                } else {
                  // 业务错误
                  const errorMessage = data.message || data.msg || '请求失败'
                  if (config.showError !== false) {
                    uni.showToast({
                      title: errorMessage,
                      icon: 'none',
                      duration: 2000
                    })
                  }
                  reject({ ...data, message: errorMessage })
                }
              } else {
                // HTTP状态码错误
                reject(this.handleError(processedResponse, config.showError))
              }
            } catch (error) {
              if (config.loading) {
                uni.hideLoading()
              }
              reject(this.handleError(error, config.showError))
            }
          },
          fail: (error) => {
            if (config.loading) {
              uni.hideLoading()
            }
            reject(this.handleError(error, config.showError))
          }
        })
      } catch (error) {
        if (config.loading) {
          uni.hideLoading()
        }
        reject(this.handleError(error, config.showError))
      }
    })
  }

  /**
   * GET请求
   * @param {String} url 请求地址
   * @param {Object} params 请求参数
   * @param {Object} config 请求配置
   * @returns {Promise} 请求Promise
   */
  get(url, params = {}, config = {}) {
    return this.request({
      url,
      method: 'GET',
      data: params,
      ...config
    })
  }

  /**
   * POST请求
   * @param {String} url 请求地址
   * @param {Object} data 请求数据
   * @param {Object} config 请求配置
   * @returns {Promise} 请求Promise
   */
  post(url, data = {}, config = {}) {
    return this.request({
      url,
      method: 'POST',
      data,
      ...config
    })
  }

  /**
   * PUT请求
   * @param {String} url 请求地址
   * @param {Object} data 请求数据
   * @param {Object} config 请求配置
   * @returns {Promise} 请求Promise
   */
  put(url, data = {}, config = {}) {
    return this.request({
      url,
      method: 'PUT',
      data,
      ...config
    })
  }

  /**
   * DELETE请求
   * @param {String} url 请求地址
   * @param {Object} params 请求参数
   * @param {Object} config 请求配置
   * @returns {Promise} 请求Promise
   */
  delete(url, params = {}, config = {}) {
    return this.request({
      url,
      method: 'DELETE',
      data: params,
      ...config
    })
  }

  /**
   * 文件上传
   * @param {String} url 上传地址
   * @param {Object} options 上传配置
   * @returns {Promise} 上传Promise
   */
  upload(url, options = {}) {
    return new Promise((resolve, reject) => {
      const {
        filePath,
        name = 'file',
        formData = {},
        header = {},
        loading = true,
        loadingText = '上传中...',
        showError = true
      } = options

      // 处理URL
      const uploadUrl = url.startsWith('http') ? url : this.baseURL + url

      // 添加token
      const token = uni.getStorageSync('token')
      if (token) {
        header.Authorization = `Bearer ${token}`
      }

      // 显示loading
      if (loading) {
        uni.showLoading({
          title: loadingText,
          mask: true
        })
      }

      uni.uploadFile({
        url: uploadUrl,
        filePath,
        name,
        formData,
        header,
        success: (response) => {
          if (loading) {
            uni.hideLoading()
          }

          try {
            const data = JSON.parse(response.data)
            if (data.code === 0 || data.success === true) {
              resolve(data.data || data)
            } else {
              const errorMessage = data.message || data.msg || '上传失败'
              if (showError) {
                uni.showToast({
                  title: errorMessage,
                  icon: 'none'
                })
              }
              reject({ ...data, message: errorMessage })
            }
          } catch (error) {
            reject(this.handleError(error, showError))
          }
        },
        fail: (error) => {
          if (loading) {
            uni.hideLoading()
          }
          reject(this.handleError(error, showError))
        }
      })
    })
  }
}

// 创建请求实例
const request = new Request()

// 设置默认请求拦截器
request.setRequestInterceptor(
  config => {
    // 可以在这里添加通用的请求头、参数等
    console.log('请求发送前:', config)
    return config
  },
  error => {
    console.error('请求拦截器错误:', error)
    return Promise.reject(error)
  }
)

// 设置默认响应拦截器
request.setResponseInterceptor(
  response => {
    // 可以在这里处理通用的响应逻辑
    console.log('响应数据:', response)
    if (response.data.code === 401) {
      uni.navigateTo({
        url: '/pages/login/index'
      })
    }
    return response
  },
  error => {
    console.error('响应拦截器错误:', error)
    return Promise.reject(error)
  }
)

export default request
